//import com.sun.xml.internal.bind.v2.runtime.RuntimeUtil.ToStringAdapter;

/**
 * @(#)Individual.java
 *
 *
 * @niv vaizer 31731805 and ilana gal
 * @version 1.00 2009/2/23
 */


public abstract class Individual implements Comparable, Cloneable, Variable {
	private final static double BEST_FITNESS = 0;
	private double fitness;

    public Individual() {
    	fitness = Double.NaN;
    }

    public double getFitness() {
    	if (Double.isNaN(fitness)) {
    		fitness = evaluate();
    	}
    	return fitness;
    }

    public void setFitness(double fitness) {
    	if (fitness >= BEST_FITNESS) {
    		this.fitness = fitness;
    	}else {
    		System.err.println("Individual setFitness was set to a negative value");
    		//throw new RuntimeException (e);
    	}
    }
    
    public Individual copyOf() {
    	Individual copyOfOther = this.clone();
    	copyOfOther.setFitness(this.fitness);
    	return copyOfOther;
    }
    
    public boolean isIdeal() {
    	boolean ans=false;
    	if (getFitness()==BEST_FITNESS) {
    		ans=true;
    	}
    	return ans;
    }

    public int compareTo(Object obj) {
    	int ans=0;
    	double otherFitness = ((Individual)obj).getFitness();
    	if (getFitness() > otherFitness) {
    		ans=1;
    	} else if (getFitness() < otherFitness) {
    		ans=-1;
    	}
    	return ans;
    }

    public Individual clone() {
    	Individual other;
    	try {
    		other = (Individual)super.clone();
    		other.fitness = Double.NaN;
    	}
    	catch (CloneNotSupportedException e) {
    		System.err.println("Caught an Exception while cloning individual: "
                     + e.getMessage());
    		throw new RuntimeException (e);
    	}
    	return other;
    }

    public String toString(){
    	String ans = "fitness="+fitness;
    	return ans;
    }
    public abstract Individual mutate();

    public abstract Individual crossover(Individual other);

    protected abstract double evaluate();
}